package org.momo.rpc.springboot.starter.bootstrap;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.momo.rpc.annotion.Retry;
import org.momo.rpc.bootstrap.model.ProviderMetaInfo;
import org.momo.rpc.config.config.RpcConfig;
import org.momo.rpc.config.RpcConfigLoader;
import org.momo.rpc.extention.ExtensionLoader;
import org.momo.rpc.registry.ProviderRegistry;
import org.momo.rpc.provider.model.ProviderRegistryInfo;
import org.momo.rpc.provider.ServiceProvider;
import org.momo.rpc.springboot.starter.annotion.RpcService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class RpcServiceRegistry implements BeanPostProcessor {

    RpcConfig rpcConfig = RpcConfigLoader.getRpcConfig();

    ProviderRegistry providerRegistry = ExtensionLoader.getExtensionLoader(ProviderRegistry.class).getExtension(rpcConfig.getRegistry());

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class<?> serviceClass = bean.getClass();

        if (serviceClass.isAnnotationPresent(RpcService.class)) {
            RpcService rpcService = serviceClass.getAnnotation(RpcService.class);
            Class<?>[] interfaces = serviceClass.getInterfaces();
            if(interfaces.length != 1) {
                log.error("Cannot register service {}, it must can only implement one interface!", serviceClass.getName());
                return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
            }

            String serviceName = StrUtil.isBlank(rpcService.serviceName())? interfaces[0].getName() : rpcService.serviceName();

            ProviderMetaInfo providerMetaInfo = new ProviderMetaInfo(serviceClass, serviceName, rpcService.serviceVersion());

            // 本地注册 类名->实现类
            ServiceProvider.provideService(providerMetaInfo);

            // 注册中心注册 服务名+地址->服务元信息
            ProviderRegistryInfo metaInfo = new ProviderRegistryInfo(serviceName, rpcService.serviceVersion(), rpcConfig.getServerHost(), rpcConfig.getServerPort());
            providerRegistry.register(metaInfo);

            List<String> retryMethods = new ArrayList<>();
            for(Method method : serviceClass.getMethods()) {
                if(method.isAnnotationPresent(Retry.class)) {
                    Retry retry = method.getAnnotation(Retry.class);
                    if(retry.canRetry()) {
                        retryMethods.add(method.getName());
                    }
                }
            }
            providerRegistry.registerRetryMethod(serviceName, rpcService.serviceVersion(), retryMethods);
        }

        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }

}
